package com.ruoyi.common.utils.file;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.Random;

/**
 * 文件生成工具类
 * 可以生成指定大小和格式的文件
 * 大小单位：KB, MB, GB（最大不超过1GB）
 * 文件格式：txt, xml, json等
 */
public class FileGenerator {

    // 大小单位常量
    public static final String UNIT_KB = "KB";
    public static final String UNIT_MB = "MB";
    public static final String UNIT_GB = "GB";

    // 文件格式常量
    public static final String FORMAT_TXT = "txt";
    public static final String FORMAT_XML = "xml";
    public static final String FORMAT_JSON = "json";
    public static final String FORMAT_CSV = "csv";

    // 最大文件大小：1GB
    private static final long MAX_FILE_SIZE = 1024 * 1024 * 1024L; // 1GB in bytes

    /**
     * 生成指定大小和格式的文件
     *
     * @param filePath 文件路径
     * @param size 文件大小
     * @param unit 大小单位 (KB, MB, GB)
     * @param format 文件格式 (txt, xml, json, csv)
     * @throws IllegalArgumentException 当参数不合法时抛出
     * @throws IOException 当文件写入失败时抛出
     */
    public static void generateFile(String filePath, int size, String unit, String format)
            throws IllegalArgumentException, IOException {

        // 参数验证
        validateParameters(size, unit, format);

        // 计算文件大小（字节）
        long fileSizeInBytes = calculateFileSize(size, unit);

        // 确保文件扩展名正确
        File file = new File(filePath);
        if (!file.getName().toLowerCase().endsWith("." + format.toLowerCase())) {
            file = new File(file.getParent(),
                    file.getName() + "." + format.toLowerCase());
        }

        // 创建父目录
        File parentDir = file.getParentFile();
        if (parentDir != null && !parentDir.exists()) {
            parentDir.mkdirs();
        }

        // 根据格式生成文件内容
        generateFileContent(file, fileSizeInBytes, format);

        System.out.println("文件生成成功: " + file.getAbsolutePath());
        System.out.println("文件大小: " + size + " " + unit + " (" + fileSizeInBytes + " 字节)");
        System.out.println("文件格式: " + format);
    }

    /**
     * 参数验证
     */
    private static void validateParameters(int size, String unit, String format) {
        if (size <= 0) {
            throw new IllegalArgumentException("文件大小必须大于0");
        }

        // 验证单位
        if (!UNIT_KB.equalsIgnoreCase(unit) &&
                !UNIT_MB.equalsIgnoreCase(unit) &&
                !UNIT_GB.equalsIgnoreCase(unit)) {
            throw new IllegalArgumentException("不支持的尺寸单位: " + unit + "，支持的单位: KB, MB, GB");
        }

        // 验证格式
        if (!FORMAT_TXT.equalsIgnoreCase(format) &&
                !FORMAT_XML.equalsIgnoreCase(format) &&
                !FORMAT_JSON.equalsIgnoreCase(format) &&
                !FORMAT_CSV.equalsIgnoreCase(format)) {
            throw new IllegalArgumentException("不支持的文件格式: " + format + "，支持的格式: txt, xml, json, csv");
        }

        // 验证大小不超过1GB
        long fileSizeInBytes = calculateFileSize(size, unit);
        if (fileSizeInBytes > MAX_FILE_SIZE) {
            throw new IllegalArgumentException("文件大小不能超过1GB");
        }
    }

    /**
     * 计算文件大小（字节）
     */
    private static long calculateFileSize(int size, String unit) {
        switch (unit.toUpperCase()) {
            case UNIT_KB:
                return size * 1024L;
            case UNIT_MB:
                return size * 1024L * 1024L;
            case UNIT_GB:
                return size * 1024L * 1024L * 1024L;
            default:
                throw new IllegalArgumentException("不支持的尺寸单位: " + unit);
        }
    }

    /**
     * 生成文件内容
     */
    private static void generateFileContent(File file, long fileSizeInBytes, String format)
            throws IOException {

        switch (format.toLowerCase()) {
            case FORMAT_TXT:
                generateTextFile(file, fileSizeInBytes);
                break;
            case FORMAT_XML:
                generateXmlFile(file, fileSizeInBytes);
                break;
            case FORMAT_JSON:
                generateJsonFile(file, fileSizeInBytes);
                break;
            case FORMAT_CSV:
                generateCsvFile(file, fileSizeInBytes);
                break;
            default:
                throw new IllegalArgumentException("不支持的格式: " + format);
        }
    }

    /**
     * 生成文本文件
     */
    private static void generateTextFile(File file, long fileSizeInBytes) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {

            Random random = new Random();
            long bytesWritten = 0;

            while (bytesWritten < fileSizeInBytes) {
                String line = generateRandomTextLine(random, 50) + "\n";
                writer.write(line);
                bytesWritten += line.getBytes(StandardCharsets.UTF_8).length;

                // 如果超过目标大小，提前退出
                if (bytesWritten >= fileSizeInBytes) {
                    break;
                }
            }
        }
    }

    /**
     * 生成XML文件
     */
    private static void generateXmlFile(File file, long fileSizeInBytes) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {

            // XML头
            String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<data>\n";
            writer.write(header);
            long bytesWritten = header.getBytes(StandardCharsets.UTF_8).length;

            Random random = new Random();
            int itemCount = 0;

            while (bytesWritten < fileSizeInBytes) {
                String item = generateXmlItem(random, itemCount++);
                writer.write(item);
                bytesWritten += item.getBytes(StandardCharsets.UTF_8).length;

                // 如果超过目标大小，提前退出
                if (bytesWritten >= fileSizeInBytes) {
                    break;
                }
            }

            // XML尾部
            String footer = "</data>";
            writer.write(footer);
        }
    }

    /**
     * 生成JSON文件
     */
    private static void generateJsonFile(File file, long fileSizeInBytes) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {

            writer.write("{\n  \"items\": [\n");
            long bytesWritten = "{\n  \"items\": [\n".getBytes(StandardCharsets.UTF_8).length;

            Random random = new Random();
            int itemCount = 0;
            boolean firstItem = true;

            while (bytesWritten < fileSizeInBytes) {
                String item = generateJsonItem(random, itemCount++);
                if (!firstItem) {
                    writer.write(",\n");
                    bytesWritten += 2;
                }
                writer.write(item);
                bytesWritten += item.getBytes(StandardCharsets.UTF_8).length;
                firstItem = false;

                // 如果超过目标大小，提前退出
                if (bytesWritten >= fileSizeInBytes) {
                    break;
                }
            }

            writer.write("\n  ]\n}");
        }
    }

    /**
     * 生成CSV文件
     */
    private static void generateCsvFile(File file, long fileSizeInBytes) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) {

            // CSV头
            String header = "id,name,value,description\n";
            writer.write(header);
            long bytesWritten = header.getBytes(StandardCharsets.UTF_8).length;

            Random random = new Random();
            int rowCount = 0;

            while (bytesWritten < fileSizeInBytes) {
                String row = generateCsvRow(random, rowCount++);
                writer.write(row);
                bytesWritten += row.getBytes(StandardCharsets.UTF_8).length;

                // 如果超过目标大小，提前退出
                if (bytesWritten >= fileSizeInBytes) {
                    break;
                }
            }
        }
    }

    /**
     * 生成随机文本行
     */
    private static String generateRandomTextLine(Random random, int maxLength) {
        String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 ";
        int length = random.nextInt(maxLength) + 10; // 10到maxLength+10个字符

        StringBuilder sb = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            sb.append(characters.charAt(random.nextInt(characters.length())));
        }

        return sb.toString();
    }

    /**
     * 生成XML项目
     */
    private static String generateXmlItem(Random random, int id) {
        return String.format("  <item id=\"%d\">\n    <name>%s</name>\n    <value>%d</value>\n  </item>\n",
                id, generateRandomTextLine(random, 20), random.nextInt(1000));
    }

    /**
     * 生成JSON项目
     */
    private static String generateJsonItem(Random random, int id) {
        return String.format("    {\"id\": %d, \"name\": \"%s\", \"value\": %d}",
                id, generateRandomTextLine(random, 20).replace("\"", "\\\""), random.nextInt(1000));
    }

    /**
     * 生成CSV行
     */
    private static String generateCsvRow(Random random, int id) {
        return String.format("%d,%s,%d,%s\n",
                id,
                "Item" + id,
                random.nextInt(1000),
                generateRandomTextLine(random, 30).replace(",", ";"));
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
//        try {
//            // 测试生成不同格式和大小的文件
//            generateFile("test.txt", 10, UNIT_KB, FORMAT_TXT);
//            generateFile("test.xml", 100, UNIT_KB, FORMAT_XML);
//            generateFile("test.json", 1, UNIT_MB, FORMAT_JSON);
//            generateFile("test.csv", 50, UNIT_KB, FORMAT_CSV);
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        String currentWorkingDir = System.getProperty("user.dir");
        System.out.println("当前工作目录: " + currentWorkingDir);
    }
}